home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / ddj1291.zip / STAT.ZIP / SOURCE.ZIP / PAUTIL.C < prev    next >
C/C++ Source or Header  |  1990-05-09  |  14KB  |  474 lines

  1. /*
  2. ** File:    pautil.c
  3. **
  4. **        Copyright 1990
  5. **        Fred Motteler and Applied Microsystems Corporation
  6. **        All Rights Reserved
  7. **
  8. ** Description:    Utility functions used by the statistical performance
  9. **        analysis package.
  10. */
  11.  
  12. #include <stdio.h>
  13. #include <ctype.h>
  14. #include <string.h>
  15. #include <stdlib.h>
  16. #include <fcntl.h>
  17. #include "padef.h"
  18.  
  19. /* Debugging level flag, pick one */
  20. int pa_debugN = PA_NO_DEBUG;
  21. /* int pa_debugN = PA_SER_IN; */
  22.  
  23. /*
  24. ** Function:    int pa_hextobin( int charN )
  25. **
  26. ** Description:    This function converts the ASCII hexidecimal character charN
  27. **        to a binary value 0 to 15.  If the input character is not
  28. **        a valid hexidecimal digit, then a -1 is returned.
  29. */
  30. int
  31. pa_hextobin( charN )
  32. int charN;            /* Character to convert */
  33. {
  34.     if( (charN >= (int)'0') && (charN <= (int)'9')) return( charN - (int)'0' );
  35.     if( (charN >= (int)'A') && (charN <= (int)'F')) return( charN - (int)'7' );
  36.     if( (charN >= (int)'a') && (charN <= (int)'f')) return( charN - (int)'W' );
  37.     return( -1 );        /* Not a hex character */
  38. }
  39.  
  40. /*
  41. ** Function:    int pa_hitcomp(struct padata *a, struct padata *b)
  42. **
  43. ** Description:    This function is compares the magnitude of a->hitsL and
  44. **        b->hitsL.  It is used by the ANSI qsort() function to
  45. **        sort the pointers in patableAHP according to the number
  46. **        of program counter "hits" within each function.  It returns
  47. **        1, 0, or -1 depending on the relative magnitude of a->hitsL and b->hitsL.
  48. */
  49. int
  50. pa_hitcomp(a, b)
  51. struct padata **a;
  52. struct padata **b;
  53. {
  54.     if (((*b)->hitsL) > ((*a)->hitsL)) return(1);
  55.     if (((*b)->hitsL) < ((*a)->hitsL)) return(-1);
  56.     return(0);
  57. }
  58.  
  59. /*
  60. ** Function:    int pa_addrcomp(struct padata *a, struct padata *b)
  61. **
  62. ** Description:    This function is compares the magnitude of a->addressL and
  63. **        b->addressL.  It is used by the ANSI qsort() functions to
  64. **        sort the pointers in patableAHP. It returns 1, 0, or -1
  65. **        depending on the relative magnitude of a->addressL and
  66. **        b->addressL.
  67. */
  68. int
  69. pa_addrcomp(a, b)
  70. struct padata **a;
  71. struct padata **b;
  72. {
  73.     if (((*b)->addressL) > ((*a)->addressL)) return(-1);
  74.     if (((*b)->addressL) < ((*a)->addressL)) return(1);
  75.     return(0);
  76. }
  77.  
  78. /*
  79. ** Function:    char *pa_strsrch( stringBP, searchBP )
  80. **
  81. ** Description:    Search for the first occurance of string "searchBP" in
  82. **        "stringBP".  If found, then return a pointer to the first
  83. **        occurance of searchBP in stringBP.  If not found, then
  84. **        return a NULL pointer.
  85. */
  86. char *
  87. pa_strsrch( stringBP, searchBP )
  88. char *stringBP;            /* String to search */
  89. char *searchBP;            /* String being searched for */
  90. {
  91.     int len_strN;        /* Length of string to search */
  92.     int len_srchN;        /* Length of string being searched for */
  93.     int searchN;
  94.  
  95.     len_strN = strlen(stringBP);
  96.     len_srchN = strlen(searchBP);
  97.     searchN = len_srchN;
  98.  
  99.     /* Search for the string only if the string to be searched is longer than
  100.      * or equal in length to the string being searched for. */
  101.     if (len_strN >= len_srchN)
  102.     {
  103.     /* Search only if the remaining portion of the string to be searched
  104.      * is longer than or equal in length to the string being searched
  105.      * for. */
  106.     while( len_strN >= len_srchN++ ) {
  107.         if (strncmp( searchBP, stringBP, searchN) == 0)
  108.         return( stringBP );
  109.         stringBP++;
  110.     }
  111.     }
  112.     return( (char *) NULL );
  113. }
  114.  
  115. /*
  116. ** Function:    int paconfig( FILE *formatFP, char *idstrPC, char *fieldstrPC )
  117. **
  118. ** Description:    The function searches the configuration file for the
  119. **        field specified in the string pointed to by idstrPC.  The
  120. **        string value in the field is returned in the buffer pointed
  121. **        to by fieldstrPC.
  122. **
  123. **        For example, in the line:
  124. **
  125. **            START_ID:"Symbols by value"
  126. **
  127. **        START_ID is the field identifier, and "Symbols by value" is
  128. **        the field value.  The double quotes are required to delimit
  129. **        the field value and are removed when the value string is
  130. **        returned to the calling program.  A field value string of
  131. **        "" is legal and results in a empty string being returned.
  132. **
  133. **        This function returns 0 if the operation is successful,
  134. **        otherwise and error code is return.
  135. */
  136. int
  137. paconfig(formatFP, idstrPC, fieldstrPC)
  138. FILE *formatFP;            /* Configuration file */
  139. char *idstrPC;            /* String giving field to find */
  140. char *fieldstrPC;        /* Pointer to found field */
  141. {
  142.     char lineAB[PA_LINE_LEN];    /* Local buf for line read from config file */
  143.     char *tempPC;        /* Working pointer */
  144.  
  145.     /* Seek to the start of the file */
  146.     if (fseek(formatFP, 0, 0) == (-1))
  147.     return(PA_CFG_SEEK_E);
  148.  
  149.     /* Search for the field identifier */
  150.     while (fgets(lineAB, PA_LINE_LEN, formatFP) != (char *) NULL)
  151.     {
  152.     /* Search the line for the string that preceeds the
  153.      * string used to start reading in the data. */
  154.     if ((tempPC = strstr(lineAB, idstrPC)) != (char *) NULL)
  155.     {
  156.         /* Found the field, check the rest of the line for the entry.
  157.         ** The first and last characters should be a double quotes. */
  158.         tempPC += strlen(idstrPC);
  159.         if (*tempPC == '\0')
  160.         return(PA_FIELD_E);
  161.         else if (*tempPC != 0x22)
  162.         return(PA_BAD_DEL_E);
  163.  
  164.         /* Copy the entry to the result buffer. */
  165.         tempPC++;        /* Skip initial double quote */
  166.         strcpy(fieldstrPC, tempPC);
  167.  
  168.         /* Search for double quote terminator, and replace it with a
  169.          * a nul terminator. */
  170.         while (*fieldstrPC != 0x22)
  171.         {
  172.         if (*fieldstrPC == '\0')
  173.             return(PA_BAD_DEL_E);
  174.         else
  175.             fieldstrPC++;
  176.         }
  177.         *fieldstrPC = '\0';    /* Replace it with a nul terminator */
  178.         return(0);
  179.     }
  180.     }
  181.     /* Entry not found, return an error code. */
  182.     return(PA_CFG_FIELD_E);
  183. }
  184.  
  185. /*
  186. ** Function:    int pa_zero_hits(struct padata **bintabP, int processedN)
  187. **
  188. ** Description:    This function does a "pre-pass" of the sample bin table,
  189. **        "throwing out" all function entries that have zero program
  190. **        counter hits associated with them.
  191. **
  192. **        This is done by a simple swap of zero hit entries for non-zero
  193. **        entries.
  194. **
  195. **        The number of entries with non-zero hits counts is returned.
  196. **
  197. **        Use of the construct bintabP[i] is used instead of *(bintabP+i)
  198. **        for the sake of readibility.
  199. */
  200. int
  201. pa_zero_hits(bintabP, processedN)
  202. struct padata **bintabP;    /* Pointer to a table of pointers to padata
  203.                  * data structures, these structures actually
  204.                  * contain the function name, address, and
  205.                  * number of program counter hits. */
  206. int processedN;            /* Number of entries in the pointer table. */
  207. {
  208.     int i,j;
  209.     struct padata *tempHP;    /* Temporary pointer for pre-sort */
  210.  
  211.     if ((pa_debugN & PA_GENERAL) != 0)
  212.     printf("pa_zero_hits: removing zero hits\n");
  213.     /* Loop through the sample table, searching for entries with zero hits. */
  214.     for (i = 0; i < (processedN - 1); i++)
  215.     {
  216.     /* Check if the current hitsL count is zero */
  217.     if ((bintabP[i]->hitsL) == 0L)
  218.     {
  219.         /* The current hitsL count is zero, search for the first non-zero
  220.          * hitL value and swap the two... */
  221.         for( j = i + 1; j < processedN; j++)
  222.         {
  223.         if ((bintabP[j]->hitsL) != 0L)
  224.         {
  225.             tempHP = bintabP[j];
  226.             bintabP[j] = bintabP[i];
  227.             bintabP[i] = tempHP;
  228.             break;
  229.         }
  230.         }
  231.         /* Check if all remaining elements are zero, if so, then quit. */
  232.         if (j == processedN)
  233.         break;
  234.     }
  235.     }
  236.     /* The value of i gives the location of the first zero entry. */
  237.     if ((pa_debugN & PA_GENERAL) != 0)
  238.     printf("pa_zero_hits: %d bins with samples\n",i);
  239.     return(i);
  240. }
  241.  
  242. /*
  243. ** Function:    int pa_bstuff(char *sampfileS, struct padata **bintabP,
  244. **              int processedN)
  245. **
  246. ** Description:    This function reads the sample file whose name is given
  247. **        in the string sampfileS.  The value of processedN gives
  248. **        the number of global symbol "bins" in the table pointed
  249. **        to by bintabP.  bintabP is actually a pointer to a table
  250. **        pointers to padata structures that contain the symbol,
  251. **        address, and hit count information.
  252. **
  253. **        Once the sample file has been processed, any "bins"
  254. **        with zero hits are effectively removed, and the resulting
  255. **        bins are sorted according to the number of hits in each
  256. **        bin.
  257. **
  258. **        Zero is returned upon successful completion of reading
  259. **        the sample file in and incremented the appropriate
  260. **        sampling "bins" in the padata structures.
  261. */
  262. int
  263. pa_bstuff(sampfileS, bintabP, processedNP)
  264. char *sampfileS;        /* Sample file to process */
  265. struct padata **bintabP;    /* Pntr to table of pntrs to padata structs
  266.                  * that contain function, address, and hit
  267.                  * values. */
  268. int *processedNP;        /* Pntr to number of globals in padata table */
  269. {
  270.     int handleN;        /* Sample file handle */
  271.     unsigned long pcvalueL;    /* Value of pc read from sample file */
  272.     int readsizeN;        /* Number of bytes read from sample file */
  273.     int stepN;            /* Current binary search step size */
  274.     int curbinN;        /* Current index of element being compared */
  275.     int hitbinsN;        /* Number of bins with hits */
  276.     int i;            /* General index */
  277.  
  278.     /* Read the samples from a binary file. */
  279.     if ((handleN = open (sampfileS, (O_RDONLY | O_RAW), 0)) == (-1))
  280.     return(PA_NO_PC_FILE_E);
  281.     while ((readsizeN = read( handleN, ((char *) &pcvalueL), 4)) == 4)
  282.     {
  283.     if ((pa_debugN & PA_GENERAL) != 0)
  284.          printf("pa_bstuff: sample value: %lx\n", pcvalueL);
  285.  
  286.     /* Do a binary search for the proper bin to increment. */
  287.     stepN = *processedNP >> 1;
  288.     curbinN = stepN;        /* Start in the middle */
  289.  
  290.     /* Loop until we find the right bin */
  291.     while (((bintabP[curbinN]->addressL) > pcvalueL) ||
  292.         ((bintabP[curbinN+1]->addressL) <= pcvalueL))
  293.     {
  294.         /* Half the step size. */
  295.         if (stepN > 1)
  296.         stepN >>= 1;
  297.         if (stepN == 0)
  298.         return(PA_BSTEP_ZERO_E);
  299.  
  300.         /* Check if pc value is less than current bin lower bound. */
  301.         if ((bintabP[curbinN]->addressL) > pcvalueL)
  302.         {
  303.         curbinN -= stepN;
  304.         if (curbinN < 0)
  305.             curbinN = 0;
  306.         }
  307.         /* Check if pc value is greater than current bin upper bound. */
  308.         else if ((bintabP[curbinN+1]->addressL) <= pcvalueL)
  309.         {
  310.         curbinN += stepN;
  311.         if (curbinN >= *processedNP)
  312.             curbinN = *processedNP - 1;
  313.         }
  314.     }
  315.     /* Increment the appropriate bin. */
  316.     (bintabP[curbinN]->hitsL)++;
  317.     }
  318.  
  319.     /* Done reading in the pc sample file. */
  320.     close( handleN );
  321.     if (remove(sampfileS) != 0)
  322.     return(PA_NO_PC_DEL_E);
  323.  
  324.     /* Check for any problems reading in the sample file. */
  325.     if (readsizeN == EOF)
  326.     return(PA_NO_PC_RD_E);
  327.  
  328.     if ((pa_debugN & PA_GENERAL) != 0)
  329.     {
  330.     printf("%d global symbols\n",*processedNP);
  331.     printf("Dump of table sorted by address, with sample counts\n");
  332.     for (i = 0; i < *processedNP; i++)
  333.     {
  334.         printf("%s  %lx  %ld\n",
  335.         ((bintabP[i])->symbolAB),
  336.         ((bintabP[i])->addressL),
  337.         ((bintabP[i])->hitsL));
  338.     }
  339.     }
  340.  
  341.     /* Throw out any sample bins that did not get any pc hits. */
  342.     if((hitbinsN = pa_zero_hits(bintabP, *processedNP)) == 0)
  343.     return(PA_NO_HIT_BINS_E);
  344.  
  345.     /* The map file has been read in, now sort it according to value. */
  346.     qsort(bintabP, hitbinsN, sizeof(struct padata *), pa_hitcomp);
  347.     return(0);
  348. }
  349.  
  350. /*
  351. ** Function:    void pa_error(int errorN)
  352. **
  353. ** Description:    This function prints out an error message that corresponds
  354. **        to the given error message.
  355. */
  356. void
  357. pa_error(errorN)
  358. int errorN;            /* Error code of message to print. */
  359. {
  360.     switch(errorN)
  361.     {
  362.       case PA_BAD_HEX_E:
  363.     printf("Hex digit expected\n");
  364.     break;
  365.       case PA_NO_SYMBOL_E:
  366.     printf("Address value with no symbol\n");
  367.     break;
  368.       case PA_EARLY_END_E:
  369.     printf("File ended unexpectedly\n");
  370.     break;
  371.       case PA_TAB_FULL_E:
  372.     printf("Map table is full\n");
  373.     break;
  374.       case PA_NO_MEM_E:
  375.     printf("Out of memory\n");
  376.     break;
  377.       case PA_NO_WHERE_E:
  378.     printf("Can't exec pawhere.exe\n");
  379.     break;
  380.       case PA_NO_TMP_E:
  381.     printf("Can't find pawhere.tmp\n");
  382.     break;
  383.       case PA_BAD_TMP_E:
  384.     printf("Can't properly read pawhere.tmp\n");
  385.     break;
  386.       case PA_TMP_RM_E:
  387.     printf("Can't remove pawhere.tmp\n");
  388.     break;
  389.       case PA_ES_NORESP_E:
  390.     printf("ES 1800 not responding\n");
  391.     break;
  392.       case PA_NO_TUP_FILE_E:
  393.     printf("Can't open file for TUP response\n");
  394.     break;
  395.       case PA_NO_TUP_WR_E:
  396.     printf("Can't write to TUP response file\n");
  397.     break;
  398.       case PA_NOT_IMPL_E:
  399.     printf("Function not implemented\n");
  400.     break;
  401.       case PA_NO_EXEC_E:
  402.     printf("Can't exec test program\n");
  403.     break;
  404.       case PA_NO_PC_FILE_E:
  405.     printf("Can't open file for pc samples\n");
  406.     break;
  407.       case PA_NO_PC_WR_E:
  408.     printf("Can't write to pc sample file\n");
  409.     break;
  410.       case PA_CFG_SEEK_E:
  411.     printf("Can't seek to start of cfg file\n");
  412.     break;
  413.       case PA_CFG_FIELD_E:
  414.     printf("Can't find field in cfg file\n");
  415.     break;
  416.       case PA_FIELD_E:
  417.     printf("Field in cfg file is empty\n");
  418.     break;
  419.       case PA_BAD_DEL_E:
  420.     printf("Field has bad or no delimiter\n");
  421.     break;
  422.       case PA_BAD_ORDER_E:
  423.     printf("Bad symbol value order field\n");
  424.     break;
  425.       case PA_MAP_FMT_E:
  426.     printf("Bad map format specification\n");
  427.     break;
  428.       case PA_BSTEP_ZERO_E:
  429.     printf("Binary search step is zero\n");
  430.     break;
  431.       case PA_NO_PC_DEL_E:
  432.     printf("Can't remove pc sample file\n");
  433.     break;
  434.       case PA_NO_PC_RD_E:
  435.     printf("Can't read from pc sample file\n");
  436.     break;
  437.       case PA_NO_MAP_E:
  438.     printf("Can't open map file\n");
  439.     break;
  440.       case PA_NO_CFG_E:
  441.     printf("Can't open the configuration file\n");
  442.     break;
  443.       case PA_NO_HIT_BINS_E:
  444.     printf("No bins accumulated any hits\n");
  445.     break;
  446.       case PA_BAD_ARG_E:
  447.     printf("Bad argument passed\n");
  448.     break;
  449.       case PA_NO_LST_E:
  450.     printf("Can't open results listing file\n");
  451.     break;
  452.       case PA_NO_DRT_FILE_E:
  453.     printf("Can't open file for DRT response\n");
  454.     break;
  455.       case PA_NO_DRT_WR_E:
  456.     printf("Can't write to DRT response file\n");
  457.     break;
  458.       case PA_BAD_DRT_RD_E:
  459.      printf("Can't properly read DRT data\n");
  460.      break;
  461.       case PA_DCOUNT_OUT_E:
  462.     printf("DRT digit count is out of bounds\n");
  463.     break;
  464.       case PA_LCOUNT_OUT_E:
  465.     printf("DRT line count is out of bounds\n");
  466.     break;
  467.       default:
  468.     printf("Unrecognized error code %d\n",errorN);
  469.     break;
  470.     }
  471.     return;
  472. }
  473.  
  474.